$title Open model

* ----------------------------------------------------------------------------
* Small open economy with imperfect substitution between domestic, imported
* and exported commodities and a benchmark trade imbalance.
* Laurent Cretegny, CoPS, Monash University, Australia, 2004.
* ----------------------------------------------------------------------------

$if not exist open.gdx $call gdxxrw i=open.xls o=open.gdx index=declare

sets
  o                 commodity and sector
  f                 primary factor;

alias (o,s);

parameters
  sam(*,*)          benchmark social accounting matrix
  supply(s)         supply of output [[sppl:o]]
  interm(o,s)       intermediate demand [[intr:o*o]]
  factor(f,s)       factor demand [[fctr:f*o]]
  demand(o)         demand for consumption [[dmnd:o]]
  govdem(o)         government demand [[gvdm:o]]
  endow(f)          endowment [[endw:f]]
  export(o)         export (at fob price) [[expt:o]]
  import(o)         import (at cif price) [[impt:o]]
  bbop              balance of payments at the benchmark (surplus)
  etrn(s)           elasticity of transformation [[etrn:o]]
  esub(s)           elasticity of substitution [[esub:o]]
  esubc             elasticity of substitution for consumption [[esbc:]]
  esubm(o)          elasticity of substitution for import [[esbm:o]];

$gdxin open
$load o f etrn esub esubc esubm sam
$gdxin

interm(o,s) = sam(o,s);
factor(f,s) = sam(f,s);
demand(o) = sam(o,"ra");
endow(f) = sam("ra",f);
export(o) = sam(o,"row");
import(o) = sam("row",o);
supply(s) = sum(o, interm(o,s)) + sum(f, factor(f,s)) - export(s);
bbop = sam("row","ra");

$if not exist open.har $include gdxtohar

$ontext
$model:open

$sectors:
  y(s)              ! production
  va(s)             ! value added
  a(s)              ! aggregate supply
  e(o)              ! export index
  m(o)              ! import index
  u                 ! utility index

$commodities:
  pd(o)             ! domestic price of commodity
  pa(o)             ! price of commodity
  pva(s)            ! price index for value added
  pf(f)             ! price of primary factor
  pe(o)             ! price of export
  pm(o)             ! price of import
  pu                ! price index for utility
  pfx               ! real exchange rate

$consumers:
  ra                ! representative agent income

$prod:y(s)          t:etrn(s)
  o:pd(s)           q:supply(s)
  o:pe(s)           q:export(s)
  i:pa(o)           q:interm(o,s)
  i:pva(s)          q:(sum(f, factor(f,s)))

$prod:va(s)         s:esub(s)
  o:pva(s)          q:(sum(f, factor(f,s)))
  i:pf(f)           q:factor(f,s)

$prod:a(o)          s:esubm(o)
  o:pa(o)           q:(supply(o)+import(o))
  i:pd(o)           q:supply(o)
  i:pm(o)           q:import(o)

$prod:e(o)
  o:pfx             q:export(o)
  i:pe(o)           q:export(o)

$prod:m(o)
  o:pm(o)           q:import(o)
  i:pfx             q:import(o)

$prod:u             s:esubc
  o:pu              q:(sum(o, demand(o)))
  i:pa(o)           q:demand(o)

$demand:ra
  d:pu
  e:pf(f)           q:endow(f)
  e:pfx             q:-bbop

$report:
  v:rsupply(s)     o:pd(s)             prod:y(s)
  v:rdemand(o)     i:pa(o)             prod:u

$offtext
$sysinclude mpsgeset open

* Benchmark replication

open.iterlim = 0;
$include open.gen
solve open using mcp;
abort$(abs(open.objval) gt 1e-7) "*** open does not calibrate ! ***";
open.iterlim = 1000;

* Fixation of a numeraire to allow comparison

pu.fx = pu.l;

* Counterfactual : trade balance requirement

bbop = 0;

$include open.gen
solve open using mcp;

* Results

parameters
  res_com           results by commodity in % change from basis
  res_agg           aggregate results in % change from basis; 

res_com("supply",s) = (rsupply.l(s)/supply(s) - 1) * 100;
res_com("export",o) = (e.l(o) - 1) * 100;
res_com("import",o) = (m.l(o) - 1) * 100;
res_com("demand",o) = (rdemand.l(o)/demand(o) - 1) * 100;
res_com("price",o) = (pa.l(o) - 1) * 100;

res_agg("u") = (u.l - 1) * 100;
res_agg("pu") = (pu.l - 1) * 100;
res_agg("pfx") = (pfx.l - 1) * 100;
res_agg("ra_inc") = (ra.l/(sum(o, demand(o))) - 1) * 100;

option decimals = 6;
display res_com, res_agg;
